Work with Legacy Web Applications, Part III - Validate Forms

From Documentation
DocumentationSmall Talks2006JulyWork with Legacy Web Applications, Part III - Validate Forms
Work with Legacy Web Applications, Part III - Validate Forms

Author
Henri Chen ,Principal Engineer ,Potix Corporation
Date
July 13, 2006
Version
Applicable to ZK 2.0.0 and later.


The Purpose

This is the third article in a series of small talks to illustrate how to use ZK with 'legacy' Web applications. In this article, we talked about how to use ZK to validate the HTML form input data before it is submitted.


Preface

ZK is a complete framework, and ZK applications don't depend on HTML forms or servlets. The recommended way is to listen events and process it as required. For example, you might listen to the onOK event to process what user has entered (instead of writing a servlet to process parameters). Then, you can either redraw a portion of page or redirect to a new page. It is more intuitive and powerful.

However, ZK is designed to co-exist with current technologies. After all, it is not practical and wasteful to rewrite the whole Web application just to enable the rich experiences.

We have shown you how to cooperate ZK with HTML form, servlet, and jsp in this smalltalk and this smalltalk. In this article, we want to show you how to validate the form input values by ZK before the form is submitted. You still keep servlets that process parameters intact. The only change is to replace the HTML form submit button with a ZK button and all the other things is as it was.

The Problems

There are two problems that related to form value validation:

1. The legacy form value validation is page based. An end user fills up the form and submits to the form processing servlet. The input data is validated in that servlet and redirected to a page showing error feedback should any data validation failed. The end user then correct the error and submit again. If the user is not familiar with the form, this process can cycle serverl times. That is a frustration to the user. The ZK components with constraints come to rescue because data validation is now done immediately when the focus is tabbed away the component. The user experience is better since error message is now popup in the place and in time. However, ZK still got no way to prevent the form from submitting when the end user hit the HTML submit button; no matter the data is valid or not. How can we refuse the form submitting in this kind of situation?

2. As illustrated in another smalltalk What Data Do You Get?, when the form submit button is pressed by the user, there is no guaratee that the ZK components' value are already "ready" or "valid". The form request is sent out by the browser to the legacy form processing servlet while the ZK components would update their values asynchronously via Ajax. How do we eliminate this possible pitfall that caused from the racing condition?

The answer

To solve the first issue, we have to let ZK do the data validation for us before the form is submitted. To solve the second issue, we have to let ZK do the submit for us because ZK synchroized all Ajax requests and thus guarantee all input values are "valid" and "ready" if the "submit" command is the last command to be called.


Example: User Profile Management

Following is a ZKed form that allows end user to add User Profile.

Here is the ZUML page.

<h:form id="updateForm" action="/updateProfile" xmlns:h="http://www.w3.org/1999/xhtml">
<grid width="400px">
  <rows>
    <row>Firt Name <textbox id="firstName" name="firstName" value="John" constraint="no empty"/></row>
    <row>Last Name <textbox id="lastName" name="lastName" value="Wells" constraint="no empty"/></row>
    <row>Birthday <datebox id="birthday" name="birthday" constraint="no empty"/></row>
    <row>Title
<combobox id="title" name="title" value="Programmer" constraint="no empty">
  <comboitem label="Programmer" description="Software developer"/>
  <comboitem label="Architect" description="Software architect"/>
  <comboitem label="Project Manager" description="Techinical lead, project manager"/>
</combobox>
    </row>
    <row>Role
<listbox name="role" multiple="true">
  <listitem value="1" label="Determine need"/>
  <listitem value="2" label="Evaluate products/sesrvices"/>
  <listitem value="3" label="Recommend products/sesrvices"/>
  <listitem value="4" label="Implement products/sesrvices"/>
  <listitem value="5" label="Techinical decision maker"/>
  <listitem value="6" label="Financial decision maker"/>
</listbox>
    </row>
    <row>
      <h:input type="submit" value="Update"/>
      <h:input type="reset"/>
    </row>
  </rows>
</grid>
</h:form>


And, the snapshot is as follows.

Profile.gif


Validate Input Data

Now we want to validate input data by ZK before the form is submitted. How to do that?

1. Apparently we have to replace the legacy HTML submit button with a ZK button so ZK gets the chance to do the validation job. The data validation code is triggered by the button's onClick event handler. Note that the ZK's constraint validation code is called inside the component's getValue() method (e.g. firstName.getValue()). Thus if any data validation failed, an WrongValueException would be thrown and the program returned from there. The error message would then popup on the browser, just like any other pure ZK application.

2. Secondly, how do we submit the form from a ZK event handler? This is the key question. The answer are these two static methods in the Clients class:

		Clients.submitForm(Component form);

		Clients.submitForm(String formId);
Developers call either of these methods to tells the ZK engine which form object to submit, and it will submit the form for you, synchornously. And of course, you have to put that method as the last one to call, so all data would be guaranteed correct and ready when the form is finally submitted to the form processing servlet.

Here is the ZUML page that replaces the HTML submit button and shows the data validation codes.

<h:form id="updateForm" action="/updateProfile" xmlns:h="http://www.w3.org/1999/xhtml">
<grid width="400px">
  <rows>
    <row>Firt Name <textbox id="firstName" name="firstName" value="John" constraint="no empty"/></row>
    <row>Last Name <textbox id="lastName" name="lastName" value="Wells" constraint="no empty"/></row>
    <row>Birthday <datebox id="birthday" name="birthday" constraint="no empty"/></row>
    <row>Title
<combobox id="title" name="title" value="Programmer" constraint="no empty">
  <comboitem label="Programmer" description="Software developer"/>
  <comboitem label="Architect" description="Software architect"/>
  <comboitem label="Project Manager" description="Techinical lead, project manager"/>
</combobox>
    </row>
    <row>Role
<listbox name="role" multiple="true">
  <listitem value="1" label="Determine need"/>
  <listitem value="2" label="Evaluate products/sesrvices"/>
  <listitem value="3" label="Recommend products/sesrvices"/>
  <listitem value="4" label="Implement products/sesrvices"/>
  <listitem value="5" label="Techinical decision maker"/>
  <listitem value="6" label="Financial decision maker"/>
</listbox>
    </row>
    <row>
      <button label="Update" onClick="update()"/>
      <h:input type="reset"/>
    </row>
  </rows>
</grid>
<zscript><![CDATA[
  void update() {
    //validate data
    firstName.getValue();
    lastName.getValue();
    birthday.getValue();
    title.getValue();
    
    //submit the form
    Clients.submitForm(updateForm);
  }
]]></zscript>
</h:form>


And, the snapshot is as follows.

Profile-valid.gif


Notes and Enhancements

The above implemenation does not handle the Enter key (The onOK event). In ZK, only window component can process the onOK event. We can put an invisible window outside the form and handle the onOK() event there. So if end user press Enter key directly, the code still works.

    <window onOK="update()">
      ...
    </window>

Summary

If you want to rewrite the user interface with ZK while keeping the servlet intact and the form data is properly validated, you could follow the steps below.

1. Replace the form submit button with a ZK button.

2. Write data validation code in the ZK button's onClick event hanlder.

3. Call Clients.submitForm() to submit the form.




Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.